<?php

namespace Lib\Base;

class Request
{

    public static $request;

    /**
     * init
     *
     * @param $request
     */
    public static function init($request)
    {
        if (isSwoole()) {
            $requestId = \Swoole\Coroutine::getuid();
            self::$request[$requestId] = $request;
        }
    }

    /**
     * 获取指定参数名的值,获取顺序$_GET,$_POST,$_COOKIE
     * @param string $name 要获取值的参数名
     * @param mixed 参数值
     */
    public static function param($name = '', $default = '', $filter = null)
    {
        $value = self::getParam($name, $default, $filter);
        if ($value === $default) {
            $value = self::postParam($name, $default, $filter);
        }
        if ($value === $default) {
            $value = self::cookieParam($name, $default, $filter);
        }
        return $value;
    }

    /**
     * 获取get请求中指定参数名的值
     * @param string $name 要获取值的参数名
     * @param mixed 参数值
     */
    public static function getParam($name = '', $default = '', $filter = null)
    {
        //$getData = php_sapi_name() == 'cli' ? $_SERVER['argv'] : $_GET;
        $getData = self::getRequestData('get');

        if (RUN_ENV == 'ulink') {
            return self::requestUlinkData($name, $getData, $default);
        } else if (RUN_ENV == 'internal') {
            if ($name == '') {
                $value = $getData;
            } else {
                $value = self::requestInternalData($name, $getData, $default);
            }

            return self::restoreData($value);
        }
    }

    /**
     * 获取post请求中指定参数名的值
     * @param string $name 要获取值的参数名
     * @param mixed 参数值
     */
    public static function postParam($name = '', $default = '', $filter = null)
    {
        //$postData = php_sapi_name() == 'cli' ? $_SERVER['argv'] : $_POST;
        $postData = self::getRequestData('post');

        if (RUN_ENV == 'ulink') {
            return self::requestUlinkData($name, $postData, $default);
        } else if (RUN_ENV == 'internal') {
            if ($name == '') {
                $value = $postData;
            } else {
                $value = self::requestInternalData($name, $postData, $default);
            }
            return self::restoreData($value);
        }
    }

    /**
     * 从cookie中获取指定参数名的值
     * @param string $name 要获取值的参数名
     * @param mixed 参数值
     */
    public static function cookieParam($name = '', $default = '', $filter = null)
    {
        //$cookieData = php_sapi_name() == 'cli' ? $_SERVER['argv'] : $_COOKIE;
        $cookieData = self::getRequestData('cookie');

        if (RUN_ENV == 'ulink') {
            return self::requestUlinkData($name, $cookieData, $default);
        } else if (RUN_ENV == 'internal') {
            if ($name == '') {
                $value = $cookieData;
            } else {
                $value = self::requestInternalData($name, $cookieData, $default);
            }

            return self::restoreData($value);
        }
    }

    /**
     * 从SERVER中获取指定参数名的值
     * @param string $name 要获取值的参数名
     * @param mixed 参数值
     * @return mixed
     */
    public static function serverParam($name = '', $default = '', $filter = null)
    {
        if (isSwoole()) {
            $requestId = \Swoole\Coroutine::getuid();
            $data = self::$request[$requestId]->server;
        } else {
            $data = $_SERVER;
        }

        if ($name == '') {
            return $data;
        } else {
            //兼容传统php模式中，像 $_SERVER['REMOTE_ADDR'] 这样，全部大写的系统变量
            if (isSwoole() && preg_match('/^[A-Z_]+$/', $name)) {
                $name = strtolower($name);
            }
            return $data[$name] ?? $default;
        }
    }

    /**
     * 从SERVER中设置值
     * @param string $name 参数名
     * @param mixed 参数值
     * @return bool
     */
    public static function setServerParam($name, $value)
    {
        if (isSwoole()) {
            $requestId = \Swoole\Coroutine::getuid();
            self::$request[$requestId]->server[$name] = $value;
        } else {
            $_SERVER[$name] = $value;
        }
        return true;
    }

    /**
     * 获取file文件上传中的指定参数名的值
     * @param string $name 要获取值的参数名
     * @param mixed 参数值
     */
    public static function fileParam($name)
    {
        if (isSwoole()) {
            $requestId = \Swoole\Coroutine::getuid();
            $data = self::$request[$requestId]->files;
        } else {
            $data = $_FILES;
        }
        return $data[$name] ?? [];
    }

    private static function restoreData($value)
    {
        $decodeValue = Common::urlDecodeDeep($value);
        //前端如果没有调用encodeURIComponent函数，那么urldecoe之后值跟原始值一样
        //如果不一样说明前端进行了encode操作，那么说明编码必定已经是UTF-8，所以不需要GBK转UTF-8
        if ($decodeValue == $value) {
            //GBK 转UTF-8，因为ame会将数据转成GBK，如果前端是encode之后传入ame，即使ame转GBK也不会有有变化（编码之后都是字母符号，UTF-8和GBK一样）
            $decodeValue = Common::charsetConvert($decodeValue);
        }
        //ame会做一次html标签到html实体的转换，收到之后，将其还原成最原始的值
        $decodeValue = Common::strReplaceDeep(array('&apos;', '&lt;', '&gt;', '&quot;'), array("'", '<', '>', '"'), $decodeValue);
        return $decodeValue;
    }

    private static function requestUlinkData($name, $data, $default)
    {
        $data[AUTH_OPENID] = isset($data['openid']) ? $data['openid'] : $default;
        unset($data['openid']);
        if ($name == '') {
            return $data;
        }

        if (is_string($name)) {
            if ($name == 'openid') {
                $name = GAME_OPENID;
            } else if ($name == 'authOpenid') {
                $name = AUTH_OPENID;
            }
            return isset($data[$name]) ? $data[$name] : $default;
        } else if (is_array($name)) {
            $rtnData = [];
            foreach ($name as $key) {
                if ($key == 'openid') {
                    $key1 = GAME_OPENID;
                } else if ($name == 'authOpenid') {
                    $key1 = AUTH_OPENID;
                } else {
                    $key1 = $key;
                }
                $rtnData[$key] = isset($data[$key1]) ? $data[$key1] : $default;
            }
            return $rtnData;
        }
    }

    private static function requestInternalData($name, $data, $default)
    {
        if ($name == '') {
            return $data;
        }
        if (is_string($name)) {
            return $data[$name] ?? $default;
        } else if (is_array($name)) {
            $rtnData = [];
            foreach ($name as $key) {
                $rtnData[$key] = $data[$key] ?? $default;
            }
            return $rtnData;
        }
    }

    /**
     * 设置全局get值
     *
     * @param $name
     * @param $value
     * @return bool
     */
    public static function setParam($name, $value)
    {
        if (isSwoole()) {
            $requestId = \Swoole\Coroutine::getuid();
            self::$request[$requestId]->get[$name] = $value;
            self::$request[$requestId]->post[$name] = $value;
            self::$request[$requestId]->cookie[$name] = $value;
        } else {
            $_GET[$name] = $value;
            $_POST[$name] = $value;
            $_COOKIE[$name] = $value;
        }

        return true;
    }

    /**
     * 设置全局get值
     *
     * @param $name
     * @param $value
     * @return bool
     */
    public static function setGetParam($name, $value)
    {
        if (isSwoole()) {
            $requestId = \Swoole\Coroutine::getuid();
            self::$request[$requestId]->get[$name] = $value;
        } else {
            $_GET[$name] = $value;
        }

        return true;
    }

    /**
     * 设置全局get值
     *
     * @param $name
     * @param $value
     * @return bool
     */
    public static function setPostParam($name, $value)
    {
        if (isSwoole()) {
            $requestId = \Swoole\Coroutine::getuid();
            self::$request[$requestId]->post[$name] = $value;
        } else {
            $_POST[$name] = $value;
        }

        return true;
    }

    /**
     * 设置全局get值
     *
     * @param $name
     * @param $value
     * @return bool
     */
    public static function setCookieParam($name, $value)
    {
        if (isSwoole()) {
            $requestId = \Swoole\Coroutine::getuid();
            self::$request[$requestId]->cookie[$name] = $value;
        } else {
            $_COOKIE[$name] = $value;
        }

        return true;
    }

    public static function destruct()
    {
        if (isSwoole()) {
            $requestId = \Swoole\Coroutine::getuid();
            if ($requestId > 0 && isset(self::$request[$requestId])) {
                //销毁log
                if (isset(self::$request[$requestId]->server['logObj'])) {
                    unset(self::$request[$requestId]->server['logObj']);
                }

                //销毁ams
                if (isset(self::$request[$requestId]->server['ams'])) {
                    unset(self::$request[$requestId]->server['ams']);
                }
                unset(self::$request[$requestId]);
            }
        }
    }

    public static function getRequest()
    {
        if (isSwoole()) {
            $requestId = \Swoole\Coroutine::getuid();
            return self::$request[$requestId];
        } else {
            return null;
        }
    }

    private static function getRequestData($type)
    {
        $result = [];
        if (php_sapi_name() == 'cli' && !isSwoole()) {
            $param = $_SERVER['argv'];

            for ($i = 1; $i < $_SERVER['argc']; $i++) {
                if (isset($param[$i]) && $param[$i] !== '') {
                    if (strpos($param[$i], '=') !== false) {
                        $arr = explode('=', $param[$i]);
                        $result[$arr[0]] = $arr[1];
                    } else {
                        $result[$i] = $param[$i];
                    }
                }
            }
        } else {
            if (isSwoole()) {
                $requestId = \Swoole\Coroutine::getuid();
                $result = $type == 'get' ? self::$request[$requestId]->get : ($type == 'post' ? self::$request[$requestId]->post : ($type == 'cookie' ? self::$request[$requestId]->cookie : []));
            } else {
                $result = $type == 'get' ? $_GET : ($type == 'post' ? $_POST : ($type == 'cookie' ? $_COOKIE : []));
            }
        }
        return $result;
    }
}
